package com.zyk.scaffold.oauth.keypool.store;

import com.zyk.scaffold.common.utils.AssertUtil;
import com.zyk.scaffold.common.utils.RSACoderUtil;
import com.zyk.scaffold.oauth.config.properties.LocalOauthServerProperties;
import com.zyk.scaffold.oauth.keypool.pojo.entry.KeyInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;


/**
 * 秘钥文件库读取，缓存
 */
@Slf4j
@Component
public class KeyPoolStore implements InitializingBean {

    private AtomicInteger size = new AtomicInteger(0);
    private Map<Integer, KeyInfo> mapId2KeyInfo = new ConcurrentHashMap<>();

    @Autowired
    private LocalOauthServerProperties localOauthServerProperties;

    @Override
    public void afterPropertiesSet() throws Exception {
//        Path path = null;
//        String keyPoolStoreFile = null;
//        if (localOauthServerProperties != null) {
//            keyPoolStoreFile = localOauthServerProperties.getKeyPool().getKeyPoolStoreFile();
//        }
//
//        if (StringUtils.isNotEmpty(keyPoolStoreFile)) {
//            path = Paths.get(keyPoolStoreFile);
//        }
//        if (path == null) {
//            path = Paths.get("keypoolstore", "keypool.store");
//            log.info("加载默认秘钥库,path:{}", path);
//        }
//        log.info("开始加载秘钥库,path:{}", path);
//        List<String> lines = Files.readAllLines(path);
//        for (int i = 0; i < lines.size(); i++) {
//            String line = lines.get(i);
//            String[] split = line.split(",");
//            AssertUtil.isFalse(split.length < 2, "秘钥文件格式不对!");
//            KeyInfo keyInfo = new KeyInfo();
//            keyInfo.setId(i);
//            keyInfo.setPublicKey(split[0]);
//            keyInfo.setPrivateKey(split[1]);
//            mapId2KeyInfo.put(i, keyInfo);
//            size.incrementAndGet();
//        }
//        log.info("秘钥库加载完成,大小：{}", size.get());
    }

    public Integer getMaxNum() {
        return size.get();
    }

    public Integer getMinNum() {
        return 0;
    }

    public List<KeyInfo> selectKeyInfo(List<Integer> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return new ArrayList<>(mapId2KeyInfo.values());
        }
        return ids.stream().map(id -> {
            KeyInfo keyInfo = mapId2KeyInfo.get(id);
            if (keyInfo == null) {
                keyInfo = buildKeyInfo(id);
            }
            return keyInfo;
        }).collect(Collectors.toList());
    }

    private KeyInfo buildKeyInfo(Integer id) {
        KeyInfo keyInfo = null;
        try {
            RSACoderUtil.KeyPairBuilder keyPairBuilder = RSACoderUtil.createdKeyPairBuilder1024();
            String privateKey = keyPairBuilder.privateKey();
            String publicKey = keyPairBuilder.publicKey();
            keyInfo = new KeyInfo();
            keyInfo.setPrivateKey(privateKey);
            keyInfo.setPublicKey(publicKey);
            keyInfo.setId(id);
            mapId2KeyInfo.put(id, keyInfo);
            size.incrementAndGet();
        } catch (Exception e) {
            e.printStackTrace();
            AssertUtil.error("创建公、私钥异常");
        }
        return keyInfo;
    }

    public static void main(String[] args) throws IOException {
        if (args.length == 0) {
            System.err.println("秘钥数量不能为空");
            System.exit(0);
        }
        Integer count = Integer.valueOf(args[0]);
        Path path = Paths.get(System.getProperty("user.dir"), "keypoolstore", "keypool.store");

        System.out.println("秘钥生成开始");
        Iterator<String> iterator = IntStream.range(0, count).boxed().map(id -> {
            RSACoderUtil.KeyPairBuilder keyPairBuilder = null;
            try {
                keyPairBuilder = RSACoderUtil.createdKeyPairBuilder1024();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("秘钥生成+1");
            return keyPairBuilder.publicKey() + "," + keyPairBuilder.privateKey();
        }).iterator();

        System.out.println("秘钥写入开始");
        Files.write(path, new Iterable<String>() {
            @Override
            public Iterator<String> iterator() {
                return iterator;
            }
        });
        System.out.println("秘钥生成完成");
    }
}
